﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using McKearney.TfsSolutionInfo.Services;
using System.IO;
using System.Windows;
using System.ComponentModel;
using System.Windows.Input;

namespace McKearney.TfsSolutionInfo.ViewModels
{
    class TfsSolutionInfoViewModel : ViewModel
    {
        private readonly ITfsInfoService _infoService = null;

        public TfsSolutionInfoViewModel(ITfsInfoService infoService)
        {
            if (infoService == null)
            {
                throw new ArgumentNullException("infoService");
            }

            _infoService = infoService;

            infoService.SolutionInfoChanged += (s, e) => UpdateInfo();

            this.RefreshInfoCommand = new ViewModelCommand(p => _infoService.RefreshInfo());
            this.ViewBranchCommand = new ViewModelCommand(p => _infoService.ViewBranch(), p => this.State == SolutionState.InTfs);

            // first time.
            UpdateInfo();
        }

        #region Commands
        public ViewModelCommand RefreshInfoCommand { get; private set; }
        public ViewModelCommand ViewBranchCommand { get; private set; }
        #endregion

        private void UpdateInfo()
        {
            // TODO: error handling
            var info = _infoService.CurrentSolutionInfo;

            this.ErrorMessage = string.Empty;

            SolutionState oldstate = State;

            this.State = info.State;

            if (string.IsNullOrEmpty(info.SolutionFileName) == true)
            {
                this.Location = string.Empty;
                this.Name = string.Empty;
            }
            else
            {
                this.Location = Path.GetDirectoryName(info.SolutionFileName);
                this.Name = Path.GetFileName(info.SolutionFileName);
            }

            this.BranchLocation = info.BranchLocation;
            this.Workspace = info.WorkspaceName;

            if (info.State == SolutionState.Error)
            {
                // TODO: more.
                this.ErrorMessage = info.Exception.Message;
            }

            if (info.State != oldstate)
            {
                bool wasError = oldstate == SolutionState.Error;
                bool isError = info.State == SolutionState.Error;

                if (wasError != isError)
                {
                    NotifyPropertyChanged("SolutionVisibility");
                    NotifyPropertyChanged("ErrorVisibility");
                }
            }
        }

        #region ErrorVisibility Property
        [Browsable(false)]
        public Visibility ErrorVisibility
        {
            get
            {
                return (State == SolutionState.Error) ? Visibility.Visible : Visibility.Collapsed;
            }
        }
        #endregion

        #region ErrorMessage Property
        private string _ErrorMessage;
        [Browsable(false)]
        public string ErrorMessage
        {
            get { return _ErrorMessage; }
            private set
            {
                if (value != _ErrorMessage)
                {
                    _ErrorMessage = value;
                    NotifyPropertyChanged("ErrorMessage");
                }
            }
        }
        #endregion


        public string Header
        {
            get
            {
                string suffix = string.Empty;
                switch (State)
                {
                    case SolutionState.NoSolution:
                        suffix = " (N/A)";
                        break;

                    case SolutionState.Error:
                        suffix = " (Error)";
                        break;

                    default:
                        suffix = string.Format(" - {0}", this.Name);
                        break;
                }
                return string.Format("Solution{0}", suffix);
            }
        }

        #region Visibility Property
        public Visibility Visibility
        {
            get 
            {
                return (State == SolutionState.Error) ? Visibility.Collapsed : Visibility.Visible; 
            }
        }
        #endregion

        public bool ShowProperties 
        {
            get { return State != SolutionState.Error && State != SolutionState.NoSolution; }
        }

        #region Location Property
        private string _Location;
        public string Location
        {
            get { return _Location; }
            private set
            {
                if (value != _Location)
                {
                    _Location = value;
                    NotifyPropertyChanged("Location");
                }
            }
        }
        #endregion

        #region Name Property
        private string _Name;
        public string Name
        {
            get { return _Name; }
            private set
            {
                if (value != _Name)
                {
                    _Name = value;
                    NotifyPropertyChanged("Name");
                    NotifyPropertyChanged("Header");
                }
            }
        }
        #endregion

        #region BranchLocation Property
        private string _BranchLocation;
        public string BranchLocation
        {
            get { return _BranchLocation; }
            set
            {
                if (value != _BranchLocation)
                {
                    _BranchLocation = value;
                    NotifyPropertyChanged("BranchLocation");
                }
            }
        }
        #endregion

        #region Workspace Property
        private string _Workspace;
        public string Workspace
        {
            get { return _Workspace; }
            private set
            {
                if (value != _Workspace)
                {
                    _Workspace = value;
                    NotifyPropertyChanged("Workspace");
                }
            }
        }
        #endregion

        #region State Property
        private SolutionState _State;
        public SolutionState State
        {
            get { return _State; }
            private set
            {
                if (value != _State)
                {
                    _State = value;
                    NotifyPropertyChanged("State");
                    NotifyPropertyChanged("StateDescription");
                    NotifyPropertyChanged("Header");
                    NotifyPropertyChanged("Visibility");
                    NotifyPropertyChanged("ShowProperties");

                    // might have
                    this.ViewBranchCommand.OnCanExecuteChanged();
                }
            }
        }
        #endregion

        #region StateDescription Property
        [DisplayName("State")]
        public string StateDescription
        {
            get
            {
                string desc = "Unknown";
                switch (_State)
                {
                    case SolutionState.NoSolution:
                        desc = "No Solution";
                        break;
                    case SolutionState.TfsNotPresent:
                        desc = "TFS Is Not Installed";
                        break;
                    case SolutionState.NotInTfs:
                        desc = "Not In TFS";
                        break;
                    case SolutionState.InTfs:
                        desc = "In TFS";
                        break;
                    case SolutionState.Error:
                        desc = "Error";
                        break;
                    default:
                        throw new InvalidOperationException(string.Format("unknown Value for Solution State: {0}", State));
                }

                return desc;
            }
        }
        #endregion

    }
}
